import json
from copy import deepcopy

from django.http import StreamingHttpResponse
from django.shortcuts import redirect
from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from rest_framework.generics import RetrieveUpdateDestroyAPIView
from io import BytesIO
from zipfile import ZipFile
from apps.base_app.utils import RestfulResponse, make_token, Mail, get_md5

import oss2  # 连接阿里云OSS

from config.constant import DEFAULT_ZIP_NAME, USER_YEAR, NOT_VALID

from rest_framework.mixins import (
    ListModelMixin,
    CreateModelMixin,
)
from apps.base_app.models import (
    SeniorList,
    StudentsList,
    WorkList,
    WorkManage,
    FileManager,
    Direction,
)
from apps.base_app.serializers import (
    SeniorListSerializer,
    StudentsListSerializer,
    WorkListSerializer,
    WorkManageSerializer, MailSerializer, LoginAndRegisterSerializer,
)


class SeniorListViewSet(
    GenericViewSet, ListModelMixin, RetrieveUpdateDestroyAPIView, CreateModelMixin
):
    queryset = SeniorList.objects.all()
    serializer_class = SeniorListSerializer

    @action(methods=['get'], detail=False)
    def get(self, request):
        return RestfulResponse(200, SeniorList.serializers(self.queryset))


class StudentsListViewSet(GenericViewSet, ListModelMixin, RetrieveUpdateDestroyAPIView, CreateModelMixin):
    queryset = StudentsList.objects.all()
    serializer_class = StudentsListSerializer

    @action(methods=['get'], detail=False)
    def get(self, request):
        return RestfulResponse(200, StudentsList.serializers(self.queryset))


class WorkListViewSet(GenericViewSet, ListModelMixin, RetrieveUpdateDestroyAPIView, CreateModelMixin):
    queryset = WorkList.objects.all()
    serializer_class = WorkListSerializer

    @action(detail=True, methods=['post'])
    def add_checker(self, request, pk):
        """
        需要传pk，还有checker: str，例子：{'checker': 程XX}
        :param pk: 主键
        :param request:
        :return:
        """
        WorkList.add_checker(pk=pk, s=request.data.get('checker'))
        return RestfulResponse(200)

    @action(detail=True, methods=['post'])
    def add_evaluate(self, request, pk):
        """
        需要传pk，还有评论等等，如：{'name': 程XX, 'evaluate': '做得很好，下次不许再做了！', 'stars': 0}
        :param pk: 作业的主键
        :param request: 注意满分(stars)是5分！
        :return:
        """
        WorkList.add_evaluate(pk=pk, evaluate=request.data.get('evaluate'),
                              name=request.data.get('name'), stars=request.data.get('stars'))
        return RestfulResponse(200)

    @action(detail=False, methods=['post'])
    def upload(self, request):  # 他们交作业的接口
        """
        需要完整的信息，比如students_list_pk, work_manage_pk, file_name, remark,
            group，direction, normative
        :param request:
        :return:
        """
        file_name = request.data.get('file_name')
        request.data['file'] = request.FILES.get(file_name)
        WorkList.submit(**request.data)
        return RestfulResponse(200)

    @action(detail=False, methods=['post'])
    def download(self, request):  # 下载一个作业的接口
        """
        只要作业名字！！！
        :param request: file_name: 文件名/路径
        :return:
        """
        file_name = request.data.get('file_name', '')
        if request.is_senior or request.user.stu_id == WorkList.get_owner(file_name):
            byte = WorkList.download(file_name)
            response = StreamingHttpResponse(byte)
            response['Content-Type'] = 'application/octet-stream'  # 传文件就得设置这个和下面的，告诉浏览
            response['Content-Disposition'] = f'attachment;filename="{file_name}"'  # 器这个响应是文件，还有文件的一些信息
            return response
        return RestfulResponse(300)

    @action(detail=False, methods=['post'])
    def downloads(self, request):
        """
        有作业名字列表，然后批量打包下载作业，人懒了，所以直接用作业名字来获取吧，，，暂时不可用！！！
        :param request: 需要参数：file_list
        :return:
        """
        file_list = request.data.get('file_list')
        if request.is_senior:
            file_dict = {}
            for file_name in file_list:
                file_dict[file_name] = WorkList.download(file_name)
            response = StreamingHttpResponse(FileManager.zip(file_dict))
            response['Content-Type'] = 'application/octet-stream'  # 传文件就得设置这个和下面的，告诉浏览
            response['Content-Disposition'] = f'attachment;filename="{DEFAULT_ZIP_NAME}"'  # 器这个响应是文件，还有文件的一些信息
            return response
        return RestfulResponse(300)

    @action(methods=['get'], detail=False)
    def get(self, request):
        return RestfulResponse(200, WorkList.serializers(self.queryset))


class WorkManageViewSet(GenericViewSet, ListModelMixin, RetrieveUpdateDestroyAPIView, CreateModelMixin):
    queryset = WorkManage.objects.all()
    serializer_class = WorkManageSerializer

    @action(methods=['get'], detail=False)
    def get(self, request):
        return RestfulResponse(200, WorkManage.serializers(self.queryset))


class LoginAndRegister(GenericViewSet):
    serializer_class = LoginAndRegisterSerializer

    @action(methods=['post'], url_name='login', url_path='', detail=False)
    def login(self, request):
        stu_id = request.data.get('stu_id', None)
        if stu_id[:4] == USER_YEAR:
            user = StudentsList.objects.filter(stu_id=stu_id).first()
            is_senior = False
        else:
            user = SeniorList.objects.filter(stu_id=stu_id).first()
            is_senior = True
        if not user:
            return RestfulResponse(403)
        if user.password != get_md5(f"{request.data.get('password', None)}"):
            return RestfulResponse(303)
        info = user.serializers((SeniorList if is_senior else StudentsList).objects.filter(stu_id=stu_id))
        return RestfulResponse(200, {
            'token': make_token({
                'stu_id': stu_id,
                'is_senior': is_senior,
                'is_root': user.is_root if is_senior else False,
            }), 'info': info,
        })

    @action(methods=['post'], url_path='register', name='register', detail=False)
    def register(self, request):
        stu_id = request.data.get('stu_id')
        if stu_id[:4] == USER_YEAR:
            if StudentsList.is_exist(**{'stu_id': stu_id}):
                return RestfulResponse(304)
            ret = StudentsList.register(**request.data)
            return RestfulResponse(200) if ret != NOT_VALID else RestfulResponse(305)
        if not SeniorList.is_exist(**{'stu_id': stu_id}):
            ret = SeniorList.register(**request.data)
            return RestfulResponse(200) if ret != NOT_VALID else RestfulResponse(305)
        return RestfulResponse(304)


class InfoSender(GenericViewSet):
    serializer_class = MailSerializer

    @action(methods=['post'], detail=False, url_path='mail', name='mail')
    def mail(self, request):
        """
        这里的file、image都是路径！！！绝对的路径！！！
        :param request:
        :return:
        """
        request.body = json.loads(request.body)
        Mail.mail(**request.body)
        return RestfulResponse(200)


@csrf_exempt
def pass_active(request):
    """
    POST，pks: []
    :param request:
    :return:
    """
    StudentsList.objects.filter(pk__in=request.POST.get('pks')).update(is_active=True)
    return RestfulResponse(200)
